package smallfrench.moteur.lexer.lexemes;

import java.util.HashMap;

/**
 * Enumération des différents types de lexèmes.
 * @author antoine1023
 *
 */
public enum TypeLexeme {

	COMMENTAIRE_BLOC("commentaire bloc"),
	COMMENTAIRE_LIGNE("commentaire simple ligne"),

	CROCHET_OUVRANT("crochet ouvrant"),
	CROCHET_FERMANT("crochet fermant"),

	ACCOLADE_OUVRANTE("accolade ouvrante"),
	ACCOLADE_FERMANTE("accolade fermante"),

	PARENTHESE_OUVRANTE("parenthese ouvrante"),
	PARENTHESE_FERMANTE("parenthese fermante"),


	POINT("signe point"),
	POINT_POINT("double point \"..\""),
	POINT_VIRGULE("signe point-virgule"),
	DEUX_POINTS("signe deux-points"),

	//--------------------------------------------------------

	/**
	 * Opérateurs binaires
	 */

	PLUS("signe plus"),

	MOINS("signe moins"),

	ETOILE("signe étoile"),

	SLASH("signe slash"),

	MODULO(true, "modulo"),

	EGAL_ASSIGN("signe égal"),

	NON(true, "non"),
	ET(true, "et"), OU(true, "ou"), OUEX(true, "ouex"),

	/**
	 * Comparaison de références, équivalent de l’opérateur <code>==</code>
	 * en Java ou de l’opérateur <code>is</code> en Python.<br>
	 * Peut être combiné avec {@link TypeLexeme#PAS} de la même manière que
	 * l’opérateur <code>is</code> peut être combiné avec le mot clé
	 * <code>not</code> en Python.
	 */
	EST(true, "est", "nest"),

	/**
	 * Sert pour la comparaison de références, en combinaison avec
	 * {@link TypeLexeme#EST}<br>
	 * Sert à former l’équivalent de l’opérateur <code>!=</code>
	 * en Java ou de l’opérateur <code>is not</code> en Python.
	 */
	PAS(true, "pas"),

	/**
	 * Comparaisons
	 */
	EGAL(true, "egal"),
	INEGAL(true, "inegal"),
	SUP(true, "sup"),
	INF(true, "inf"),
	SUPEGAL(true, "supegal"),
	INFEGAL(true, "infegal"),

	//--------------------------------------------------------

	/**
	 * Déclaration de variable
	 */
	VAR(true, "var"),

	/**
	 * Déclaration de classe
	 */
	CLASSE(true, "classe"),
	ETENDANT(true, "etendant"),

	/**
	 * Constructeur
	 */
	CONSTRUCTEUR(true, "constructeur"),

	/**
	 * Mot-clé "moi", équivalent de "this".
	 */
	MOI(true, "moi"),

	// Conditions
	SI(true, "si"),
	OUSI(true, "ousi"),
	SINON(true, "sinon"),

	ESSAYER(true, "essayer"),
	SIEXCEPTION(true, "siexception"),

	// Boucles
	TANTQUE(true, "tantque"),
	POURCHAQUE(true, "pourchaque"), DANS(true, "dans"),

	/**
	 * == <code>return</code>
	 */
	RETOUR(true, "retour"),
	/**
	 * == <code>break</code>
	 */
	FINBOUCLE(true, "finboucle"),
	/**
	 * == <code>getClass()</code>
	 */
	CLASSEDE(true, "classede"),
	/**
	 * == <code>instanceof</code>
	 */
	ESTUN(true, "estun", "estune"),

	CONST_ENTIER("nombre entier"),
	CONST_CHAINE("chaîne de caratères"),
	CONST_FLOTTANT("nombre à virgule flottante"),
	CONST_VRAI(true, "vrai"),
	CONST_FAUX(true, "faux"),

	/**
	 * equivalent <code>null</code>
	 */
	CONST_RIEN(true, "rien"),

	IDENTIFICATEUR("identificateur"),
	;



	public final String description;

	/**
	 * Les mots-clés synonymes si le lexème est un mot-clé, sinon
	 * <code>null</code>.
	 */
	private final String[] motsCles;


	TypeLexeme(String description) {
		this.description = description;
		motsCles = null;
	}

	TypeLexeme(boolean estUnMotCle, String... motsCles) {
		this.motsCles = motsCles;
		this.description = "mot-clé \"" + motsCles[0] + "\"";
	}

	/**
	 * @return La description du type.
	 */
	@Override
	public String toString() {
		return description;
	}

	/**
	 * Une map ayant pour clées tous les mots-clés ; et pour valeurs les
	 * {@link TypeLexeme} correspondants.
	 */
	private static final HashMap<String, TypeLexeme> motCles =
			new HashMap<String, TypeLexeme>();

	static {
		TypeLexeme[] types = values();
		for (TypeLexeme t : types) {
			if (t.motsCles != null) {
				String[] synonymes = t.motsCles;
				for (String s : synonymes)
					motCles.put(s, t);
			}
		}
	}

	/**
	 * 
	 * @param ident
	 * @return Le {@link TypeLexeme} correspondant ou <code>null</code>,
	 * si la chaîne <code>ident</code> passée en paramètre n’est pas un mot-clé.
	 */
	public static TypeLexeme getTypeLexeme(String ident) {
		return motCles.get(ident);
	}
}
